﻿using System;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Practices.Composite.Events;
using FXSStation.Modules.SharedInfrastructureModule.Events;
using FXSStation.Modules.SharedInfrastructureModule.BusinessClasses.Orders;
using System.Windows.Threading;
using FXSStation.Modules.SharedInfrastructureModule.BusinessClasses.Chart;
using Microsoft.Practices.Composite.Presentation.Events;
using FXSStation.Modules.SharedInfrastructureModule.BusinessClasses.Common;
using System.ComponentModel;
using FXSStation.Modules.SharedInfrastructureModule.Extentions.TileView;
using FXSStation.Modules.ChartModule.ChartData;
using System.IO;
using System.Reflection;
using System.Collections.ObjectModel;
using System.Windows.Media;
using Infragistics.Windows.Chart;
using System.Windows.Data;
using System.Windows.Input;
using FXSStation.Modules.SharedInfrastructureModule.BusinessClasses.Chart_Indicators;
using FXSStation.Modules.SharedInfrastructureModule.BusinessClasses.Currency;
using System.Windows.Media.Imaging;
using UIComposition.Infrastructure;

namespace FXSStation.Modules.ChartModule
{
    /// <summary>
    /// Interaction logic for Tester.xaml
    /// </summary>
    public partial class Tester : UserControl, INotifyPropertyChanged, ITileViewItem
    {
        #region Constructors
        public Tester()
        {
            InitializeComponent();
            this.Title = "Chart View";
            this.PostBuyOrder += new EventHandler(OnBuyOrderMade);
            this.PostSellOrder += new EventHandler(OnSellOrderMade);
            this.TickElapsed += new EventHandler(OnTickElapsed);
            timer.Tick += new EventHandler(OnTimerTickElapsed);
            liveSimulationTimer.Tick += new EventHandler(OnLiveSimulationTick);

            FileInfo fi = new FileInfo(RXSStationFileNames.ImagesPath + "Chart.png");
            if (fi.Exists)
            {
                this.Icon = new BitmapImage(new Uri(fi.FullName, UriKind.RelativeOrAbsolute));
            }
        }
        public Tester(IEventAggregator eventAggregator)
            : this()
        {
            _eventAggregator = eventAggregator;

            // Subscriging for events
            SimulationStartedEvent simulationStartedEvent = _eventAggregator.GetEvent<SimulationStartedEvent>();

            if (_subscriptionToken != null)
            {
                simulationStartedEvent.Unsubscribe(_subscriptionToken);

            }
            _subscriptionToken = simulationStartedEvent.Subscribe(OnSimulationStarted, ThreadOption.UIThread, false);

        }
        #endregion

        // affects only the last item being added to the chart
        private void OnLiveSimulationTick(object sender, EventArgs e)
        {
            
        }
        private void OnTimerTickElapsed(object sender, EventArgs e)
        {
            if (this.Simulation.SimulationMode == SimulationMode.Testing)
            {
                if (counter < ChartData.Count)
                {
                    tempChartData.Add(ChartData[counter]);
                    // INVOKE A TICK EVENT
                    CurrentPrice = (decimal)ChartData[counter].Close;
                    TickElapsed(new Tick(currentPrice), null);
                    UpdateOrdersWindowData();
                    counter++;
                }
                else
                {
                    // simulation ends
                    // reset simulation
                    counter = 0;
                    tempChartData.Clear(); ;
                }
            }
            else
            {
                // History Mode
                // no need for the timer
                timer.Stop();
            }
            textBlock1.Text = CurrentPrice.ToString();
        }

        #region Publishing Events

        void OnBuyOrderMade(object sender, EventArgs e)
        {
            _eventAggregator.GetEvent<BuyOrderMadeEvent>().Publish(sender as OrderBase);
        }
        void OnSellOrderMade(object sender, EventArgs e)
        {
            _eventAggregator.GetEvent<SellOrderMadeEvent>().Publish(sender as OrderBase);
        }
        void OnTickElapsed(object sender, EventArgs e)
        {
            _eventAggregator.GetEvent<TickElapsedEvent>().Publish(new Tick(currentPrice));
        }

        #endregion

        #region Handling Events

        void OnSimulationStarted(Simulation simulation)
        {
            // Displaying testing information
            System.Diagnostics.Debug.WriteLine(string.Format("New Simulation Started. {0} Account: {1} {0} Currency {2} {0} Frequency {3} {0} Mode : {4}", 
                Environment.NewLine, simulation.Account.Name, simulation.CurrencyPair,simulation.TickFrequency, simulation.SimulationMode));
            
            this.Simulation = simulation;
            ChartData = CacheData(simulation.CurrencyPair, simulation.TickFrequency);
            xamChart1.Series.Clear();
            
            // testing
            timer.Interval = TimeSpan.FromMinutes((int)this.Simulation.TickFrequency);
            speedSlider.Minimum = 0;
            speedSlider.Maximum = 60;
            speedSlider.ValueChanged += new RoutedPropertyChangedEventHandler<double>(speedSlider_ValueChanged);

            tempChartData.Clear();
            counter = 0;

            // for testing = speed up the timer
            speedSlider.Value = 1;

            timer.Start();

            Series candleSeries = new Series();
            candleSeries.DataMapping = "High=High;Open=Open;Close=Close;Low=Low; Label=Date";
            candleSeries.ChartType = ChartType.Candlestick;
            candleSeries.Fill = Brushes.Green;
            candleSeries.Stroke = Brushes.Black;
            candleSeries.StrokeThickness = 1;
            candleSeries.ChartParameters.Add(new ChartParameter() { Type = ChartParameterType.RectangleRounding, Value = 3 });
            candleSeries.ChartParameters.Add(new ChartParameter() { Type = ChartParameterType.CandlestickNegativeFill, Value = Brushes.White });
            candleSeries.ChartParameters.Add(new ChartParameter() { Type = ChartParameterType.CandlestickNegativeStroke, Value = Brushes.Gray });
            xamChart1.Series.Add(candleSeries);


            // test mode
            if (simulation.SimulationMode == SimulationMode.Testing)
            {
                candleSeries.DataSource = tempChartData;
                xamChart1.Axes[0].Unit = 200;

                SimpleMovingAverage sma = new SimpleMovingAverage(5, tempChartData);
                WeightedMovingAverage wma = new WeightedMovingAverage(5, tempChartData);

                movingAverageSeries = new Series();
                weightedMovingAverageSeries = new Series();

                movingAverageSeries.DataSource = sma.IndicatorData;
                movingAverageSeries.DataMapping = "Value=Value";
                movingAverageSeries.ChartType = ChartType.Line;

                weightedMovingAverageSeries.DataSource = wma.IndicatorData;
                weightedMovingAverageSeries.DataMapping = "Value=Value";
                weightedMovingAverageSeries.ChartType = ChartType.Line;
            }
            // History mode
            else
            {
                candleSeries.DataSource = ChartData;
                SimpleMovingAverage sma = new SimpleMovingAverage(5, ChartData);
                sma.Calculate();

                WeightedMovingAverage wma = new WeightedMovingAverage(5, ChartData);
                wma.Calculate();

                movingAverageSeries = new Series();
                movingAverageSeries.DataSource = sma.IndicatorData;
                movingAverageSeries.DataMapping = "Value=Value";
                movingAverageSeries.ChartType = ChartType.Line;

                weightedMovingAverageSeries = new Series();
                weightedMovingAverageSeries.DataSource = wma.IndicatorData;
                weightedMovingAverageSeries.DataMapping = "Value=Value";
                weightedMovingAverageSeries.ChartType = ChartType.Line;


                xamChart1.Axes[0].AutoRange = true;
                xamChart1.Axes[0].Unit = 200;
            }
            xamChart1.Caption.Text = String.Format("{1} Chart {0} Currency Pair: {2} {0} Frequency Time: {3}", Environment.NewLine, simulation.SimulationMode, simulation.CurrencyPair,simulation.TickFrequency);
        }

        void speedSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            this.timer.Interval = TimeSpan.FromSeconds(e.NewValue);
        }

        #endregion

        #region Fields
        private Series movingAverageSeries = new Series();
        private Series weightedMovingAverageSeries = new Series();
        private IEventAggregator _eventAggregator;
        private event EventHandler PostBuyOrder;
        private event EventHandler PostSellOrder;
        private event EventHandler TickElapsed;
        private Random random = new Random();
        private DispatcherTimer timer = new DispatcherTimer();
        private DispatcherTimer liveSimulationTimer = new DispatcherTimer();
        private ObservableCollection<StockItem> ChartData = new ObservableCollection<StockItem>();
        private ObservableCollection<StockItem> tempChartData = new ObservableCollection<StockItem>();
        private ObservableCollection<double> movingAverageData = new ObservableCollection<double>();
        private int counter = 0;
        private StockItem dummyStockItem = new StockItem();
        private Window ordersWindow = new Window();

        #endregion

        #region Properties

        public SubscriptionToken _subscriptionToken { get; set; }

        private Simulation _simulation;
        public Simulation Simulation
        {
            get { return _simulation; }
            set
            {
                _simulation = value;
                RaisePropertyChanged("Simulation");

                if (_simulation.Account != null)
                {
                    this.IsReady = true;
                    RaisePropertyChanged("IsReady");
                }
                else
                {
                    this.IsReady = false;
                    RaisePropertyChanged("IsReady");
                }
            }
        }
        private decimal currentPrice = 0;

        public decimal CurrentPrice
        {
            get { return currentPrice; }
            set
            {
                if (this.currentPrice != value)
                {
                    this.currentPrice = value;
                    RaisePropertyChanged("CurrentPrice");
                }
            }
        }
        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion

        #region ITileViewItem Members

        public string Title { get; set; }

        public object Icon { get; set; }
        private bool _isReady;
        public bool IsReady
        {
            get { return _isReady; }
            set
            {
                _isReady = value;
                RaisePropertyChanged("IsReady");
            }
        }

        #endregion

        private void xamChart1_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            HitTestArgs test = this.xamChart1.HitTest(e);
            // Try to cast the SelectedObject to a DataPoint
            DataPoint dp = test.SelectedObject as DataPoint;
            //Check to see if the cast was successful
            if (dp != null && dp.ChartParameters.Count>=4)
            {
                //TODO: Code application logic here
                tbResult.Text = string.Format("High: {1}{0}Open {2}{0}Close {3}{0}Low {4}{0}",
                Environment.NewLine,
                dp.ChartParameters[0].Value,
                    dp.ChartParameters[1].Value,
                    dp.ChartParameters[2].Value,
                    dp.ChartParameters[3].Value);
            }
            //The MouseDown event is a bubbling event. If you do not set the e.Handled property to true, this event may fire more than once.
            //e.Handled = true;
        }

        private void buyOrder_Click(object sender, RoutedEventArgs e)
        {
            // Place Buy Order
            if (!ordersWindow.IsActive)
            {
                ordersWindow.Close();
            }
            ordersWindow = new Window();
            ordersWindow.ShowInTaskbar = false;
            ordersWindow.SizeToContent = SizeToContent.WidthAndHeight;
            ordersWindow.WindowStyle = WindowStyle.ToolWindow;
            BuyOrderWindow buyOrderWindow = new BuyOrderWindow();
            buyOrderWindow.Tag = this.Simulation;
            buyOrderWindow.PostBuyOrder += new NewOrderEventHandler(buyOrderWindow_PostBuyOrder);
            buyOrderWindow.DataContext = this.CurrentPrice;
            ordersWindow.Content = buyOrderWindow;
            // position to mouse point
            ordersWindow.WindowStartupLocation = WindowStartupLocation.Manual;
            ordersWindow.Top = this.PointToScreen(Mouse.GetPosition(this)).Y - 150;
            ordersWindow.Left = this.PointToScreen(Mouse.GetPosition(this)).X - 150;
            ordersWindow.Show();
        }
        private void sellOrder_Click(object sender, RoutedEventArgs e)
        {
            if(!ordersWindow.IsActive)
            {
                ordersWindow.Close();
            }
            ordersWindow = new Window();
            ordersWindow.ShowInTaskbar = false;
            ordersWindow.SizeToContent = SizeToContent.WidthAndHeight;
            ordersWindow.WindowStyle = WindowStyle.ToolWindow;
            SellOrderWindow sellOrderWindow = new SellOrderWindow();
            sellOrderWindow.Tag = this.Simulation;
            sellOrderWindow.PostSellOrder += new NewOrderEventHandler(sellOrderWindow_PostSellOrder);
            sellOrderWindow.DataContext = this.CurrentPrice;
            ordersWindow.Content = sellOrderWindow;
            // position to mouse point
            ordersWindow.WindowStartupLocation = WindowStartupLocation.Manual;
            ordersWindow.Top = this.PointToScreen(Mouse.GetPosition(this)).Y - 150;
            ordersWindow.Left = this.PointToScreen(Mouse.GetPosition(this)).X - 150;
            ordersWindow.Show();
        }
        private void sellOrderWindow_PostSellOrder(object sender, NewOrderEventArgs e)
        {
            PostSellOrder(new OrderBase(DateTime.Now, OrderType.SellOrder, e.Amount, this.Simulation.CurrencyPair, currentPrice), null);
        }
        private void buyOrderWindow_PostBuyOrder(object sender, NewOrderEventArgs e)
        {
            PostBuyOrder(new OrderBase(DateTime.Now, OrderType.BuyOrder, e.Amount, this.Simulation.CurrencyPair, currentPrice), null);
        }
        private ObservableCollection<StockItem> CacheData(CurrencyEnum currency, TickFrequency frequency)
        {
            ImportService service = new ImportService();
            // TO DO - ADJUST DATA TO CURRENCY PAIR CHOICE
            FileInfo file = new FileInfo(String.Format(@"..\..\..\Modules\ChartData\{0}\{0}{1}.csv",currency,(int)frequency));
            if (!file.Exists)
                return new ObservableCollection<StockItem>();
            else
            {
                service.LoadData(file.FullName);
                ObservableCollection<StockItem> data = service._row_chart_data;
                return data;
            }
        }

        private void UpdateOrdersWindowData()
        {
            if (ordersWindow.Content != null)
            {
                (ordersWindow.Content as UserControl).DataContext = this.CurrentPrice;
            }
        }
        private void ResetExistingIndicators()
        {
        }

        #region Add Chart Indicators
        
        private void AddSMA_Click(object sender, RoutedEventArgs e)
        {
            MenuItem menuItem = sender as MenuItem;

            if (xamChart1.Series.IndexOf(movingAverageSeries) == -1)
            {
                xamChart1.Series.Add(movingAverageSeries);
                menuItem.IsChecked = true;
            }
            else
            {
                xamChart1.Series.Remove(movingAverageSeries);
                menuItem.IsChecked = false;
            }
        }

        private void AddWMA_Click(object sender, RoutedEventArgs e)
        {
            MenuItem menuItem = sender as MenuItem;
            if (xamChart1.Series.IndexOf(weightedMovingAverageSeries) == -1)
            {
                xamChart1.Series.Add(weightedMovingAverageSeries);
                menuItem.IsChecked = true;
            }
            else
            {
                xamChart1.Series.Remove(weightedMovingAverageSeries);
                menuItem.IsChecked = false;
            }
        }

        private void AddEMA_Click(object sender, RoutedEventArgs e)
        {

        }

        #endregion

    }
}
